﻿
using Anno.Repository;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;

namespace Anno.DynamicApi
{
    /// <summary>
    /// 执行脚本模板
    /// </summary>
    public class SqlTplExecutor : BaseExecutor
    {
        public SqlTplExecutor(ApiInfo apiInfo) : base(apiInfo, ExecutorType.SqlTpl)
        {
        }
        /// <summary>
        /// 连接配置中的connectionStrings节点名称，connectionStrings[DBName]
        /// </summary>
        public string DBName { get; set; }
        /// <summary>
        /// 脚本为“T”或存储过程“P”
        /// </summary>
        public string CmdType { get; set; } = "T";
        /// <summary>
        /// 脚本或存储过程名称
        /// </summary>
        public string Sql { get; set; }
        /// <summary>
        /// 入参前缀
        /// </summary>
        public string inputSuffix { get; set; } = "";

        /// <summary>
        /// 出参信息
        /// </summary>
        public List<ApiOutputInfo> OutputList { get; set; }

        public SqlTplExecutor(System.Xml.XmlNode xmlNode, ApiInfo apiInfo) : base(xmlNode, apiInfo, ExecutorType.SqlTpl)
        {
            if (xmlNode == null || apiInfo == null || xmlNode.NodeType == System.Xml.XmlNodeType.Comment)
            {
                return;
            }
            Init(xmlNode, apiInfo);
        }
        public SqlTplExecutor(Newtonsoft.Json.Linq.JToken xmlNode, ApiInfo apiInfo) : base(xmlNode, apiInfo, ExecutorType.SqlTpl)
        {
            if (xmlNode == null || apiInfo == null)
            {
                return;
            }
            Init(xmlNode, apiInfo);
        }
        public override void Init(System.Xml.XmlNode ExecutorNode, ApiInfo apiInfo)
        {
            base.Init(ExecutorNode, apiInfo);
            try
            {
                if (ExecutorNode == null || apiInfo == null || ExecutorNode.NodeType == System.Xml.XmlNodeType.Comment)
                {
                    return;
                }
                Name = ExecutorNode.GetXmlNodeAttributeValue("Name", Name);
                DBName = ExecutorNode.GetXmlNodeAttributeValue("DBName");
                CmdType = ExecutorNode.GetXmlNodeAttributeValue("CmdType", "T");
                Sql = ExecutorNode.GetXmlNodeAttributeValue("Sql");
                inputSuffix = ExecutorNode.GetXmlNodeAttributeValue("inputSuffix");
                if (string.IsNullOrWhiteSpace(Sql))
                {
                    Sql = ExecutorNode.InnerText;
                }
            }
            catch { }
        }
        public override void Init(Newtonsoft.Json.Linq.JToken ExecutorNode, ApiInfo apiInfo)
        {
            base.Init(ExecutorNode, apiInfo);
            try
            {
                if (ExecutorNode == null || apiInfo == null)
                {
                    return;
                }
                Name = ExecutorNode.GetXmlNodeAttributeValue("Name", Name);
                DBName = ExecutorNode.GetXmlNodeAttributeValue("DBName");
                CmdType = ExecutorNode.GetXmlNodeAttributeValue("CmdType", "T");
                Sql = ExecutorNode.GetXmlNodeAttributeValue("Sql");
                inputSuffix = ExecutorNode.GetXmlNodeAttributeValue("inputSuffix");
            }
            catch { }
        }
        /// <summary>
        /// 返回JSON对象
        /// </summary>
        public override object JObject
        {
            get
            {
                var bJObject = base.JObject as IDictionary<string, object>;

                //bJObject[nameof(Sql)] = Sql;

                var outputList = new System.Collections.Generic.List<object>();
                OutputList?.ForEach(ext => outputList.Add(ext.JObject));
                bJObject[nameof(OutputList)] = outputList;

                return bJObject;
            }
        }
        public override IDictionary<string, object> DicAttrs
        {
            get
            {
                //var outputList = new System.Collections.Generic.List<IDictionary<string, object>>();
                //OutputList?.ForEach(ext => outputList.Add(ext.DicAttrs));

                var bJObject = base.DicAttrs;

                bJObject[nameof(DBName)] = DBName;
                bJObject[nameof(CmdType)] = CmdType;
                bJObject[nameof(Sql)] = Sql;
                bJObject[nameof(inputSuffix)] = inputSuffix;
                //bJObject[nameof(OutputList)] = outputList;

                return bJObject;
            }
        }
        //---------------------------------------------------------------------------------------------------------------------------------
        protected override object Executor(object input)
        {
            //return null;
            try
            {
                var sql = this.Sql;
                var _db = Loader.IocLoader.Resolve<ISqlSugarRepository>();
                _db.ChangeDatabase(DBName);
                //--------------------------------------------------------------------------------------------------------------------------------------------------------------------
                var ReturnObj = new ApiResult();//.Success(new object());

                var sqlEntity = new SqlEntity() { CommandType = this.CmdType.ToUpper().Contains("T") ? System.Data.CommandType.Text : System.Data.CommandType.StoredProcedure };
                sqlEntity.Sql = sql;
                var arry = input.GetFieldPathValue("Array", "object");
                if (arry.IsNotNullOrEmpty_() && arry is Newtonsoft.Json.Linq.JArray jarray)
                {
                    try
                    {
                        _db.Ado.BeginTran();

                        var dataObjs = new List<object>();
                        ReturnObj.OutputData = dataObjs;

                        foreach (var item in jarray)
                        {
                            if (!item.HasValues)
                                continue;
                            var val = item.Value<object>();
                            if (val == null)
                                continue;

                            if (sqlEntity.CommandType == CommandType.StoredProcedure)
                            {
                                _db.GetSqlEntityPro(sqlEntity, val);
                            }
                            else
                            {
                                PubFun.SetSqlEntityParameter(sqlEntity, val, inputSuffix, ApiInputInfoList);
                            }
                            //--------------------------------------------------------------------------------------------------------------------------------------------------------------------
                            var ds = _db.QueryDataSet(sqlEntity);
                            if (ds == null || ds.Tables.Count == 0)
                                continue; //return ApiResult.Faild("失败，未查询到数据");
                                          //--------------------------------------------------------------------------------------------------------------------------------------------------------------------
                                          //var ReturnObj = ApiResult.Success(new object());
                                          //--------------------------------------------------------------------------------------------------------------------------------------------------------------------
                                          //从最后一个数据源中，获取返回 ResponseCode 和 ResponseDesc,判断执行是否成功
                            var lastIndex = ds.Tables.Count - 1;
                            if (ds.Tables[lastIndex].Columns.Contains(CodeField) && ds.Tables[lastIndex].Columns.Contains(MsgField))
                            {
                                ReturnObj.Status = ds.Tables[lastIndex].Rows[0].GetColumnValue(CodeField, "-1").NullToStr()
                                    .Equals(CodeSucceedValue, StringComparison.OrdinalIgnoreCase);
                                ReturnObj.Msg = ds.Tables[lastIndex].Rows[0].GetColumnValue(MsgField).NullToStr();
                                if (!ReturnObj.Status)//失败
                                {
                                    _db.Ado.RollbackTran();
                                    return ApiResult.Faild(ReturnObj.Msg);
                                }
                                ds.Tables[lastIndex].RemoveColumn(CodeField);
                                ds.Tables[lastIndex].RemoveColumn(MsgField);
                            }
                            //--------------------------------------------------------------------------------------------------------------------------------------------------------------------
                            //var dataObj = new Newtonsoft.Json.Linq.JObject();
                            //dataObjs.Add(dataObj);
                            for (var i = 0; i < ds.Tables.Count; i++)
                            {
                                var filename = "";
                                var IsArrayJson = true;
                                var actionOutputInfo = this.OutputList?.Find(f => f.DataSoureIndex == i);
                                if (actionOutputInfo != null)
                                {
                                    filename = actionOutputInfo.OutputName;
                                    IsArrayJson = actionOutputInfo.IsArray;
                                }
                                //--------------------------------------------------------------------------------------------------------------------------------------------------------------------
                                #region 给实体邦定数据
                                if (ds.Tables[i].Rows.Count > 0 && ds.Tables[i].Columns.Count > 0)
                                {
                                    if (IsArrayJson)
                                    {
                                        var lst = ds.Tables[i].ToJObject();
                                        dataObjs.Add(lst);
                                    }
                                    else
                                    {
                                        var lst = ds.Tables[i].Rows[0].ToJObject();
                                        dataObjs.Add(lst);
                                    }
                                }
                                #endregion
                            }
                        }
                        _db.Ado.CommitTran();
                    }
                    catch (Exception ex)
                    {
                        _db.Ado.RollbackTran();
                        return ApiResult.Exception(ex);
                    }
                }
                else
                {
                    if (sqlEntity.CommandType == CommandType.StoredProcedure)
                    {
                       _db.GetSqlEntityPro(sqlEntity, input);
                    }
                    else
                    {
                        PubFun.SetSqlEntityParameter(sqlEntity, input, inputSuffix, ApiInputInfoList);
                    }
                    //--------------------------------------------------------------------------------------------------------------------------------------------------------------------
                    var ds = _db.QueryDataSet(sqlEntity);
                    if (ds == null || ds.Tables.Count == 0) return ApiResult.Faild("失败，未查询到数据");
                    //--------------------------------------------------------------------------------------------------------------------------------------------------------------------
                    //var ReturnObj = ApiResult.Success(new object());
                    //--------------------------------------------------------------------------------------------------------------------------------------------------------------------
                    //从最后一个数据源中，获取返回 ResponseCode 和 ResponseDesc,判断执行是否成功
                    var lastIndex = ds.Tables.Count - 1;
                    if (ds.Tables[lastIndex].Columns.Contains(CodeField) && ds.Tables[lastIndex].Columns.Contains(MsgField))
                    {
                        ReturnObj.Status = ds.Tables[lastIndex].Rows[0].GetColumnValue(CodeField, "-1").NullToStr()
                                    .Equals(CodeSucceedValue, StringComparison.OrdinalIgnoreCase); ;
                        ReturnObj.Msg = ds.Tables[lastIndex].Rows[0].GetColumnValue(MsgField).NullToStr();
                        if (!ReturnObj.Status)//失败
                        {
                            return ApiResult.Faild(ReturnObj.Msg);
                        }
                        ds.Tables[lastIndex].RemoveColumn(CodeField);
                        ds.Tables[lastIndex].RemoveColumn(MsgField);
                    }
                    //--------------------------------------------------------------------------------------------------------------------------------------------------------------------
                    var dataObj = new Newtonsoft.Json.Linq.JObject();
                    ReturnObj.OutputData = dataObj;

                    for (var i = 0; i < ds.Tables.Count; i++)
                    {
                        var filename = "";
                        var IsArrayJson = true;
                        var actionOutputInfo = this.OutputList?.Find(f => f.DataSoureIndex == i);
                        if (actionOutputInfo != null)
                        {
                            filename = actionOutputInfo.OutputName;
                            IsArrayJson = actionOutputInfo.IsArray;
                        }
                        //--------------------------------------------------------------------------------------------------------------------------------------------------------------------
                        #region 给实体邦定数据
                        if (ds.Tables[i].Rows.Count > 0 && ds.Tables[i].Columns.Count > 0)
                        {
                            if (IsArrayJson)
                            {
                                var lst = ds.Tables[i].ToJObject();
                                if (filename.Trim().ToLower() == "data")
                                {
                                    ReturnObj.OutputData = lst;
                                }
                                else
                                {
                                    dataObj[filename] = lst;
                                }
                            }
                            else
                            {
                                var lst = ds.Tables[i].Rows[0].ToJObject();
                                if (filename.Trim().ToLower() == "data")
                                {
                                    ReturnObj.OutputData = lst;
                                }
                                else
                                {
                                    dataObj[filename] = lst;
                                }
                            }
                        }
                        #endregion
                    }
                }
                return ReturnObj;
            }
            catch (Exception ex)
            {
                return ApiResult.Exception(ex);
                //throw ex;
                //var error = ex.GetExceptionMessage();
                //Console.WriteLine(error);
                //Log.Log.Error(error);
                //return null;
            }
        }
    }
}
